package eigenfiles;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.NoSuchElementException;
import java.util.Scanner;

import javax.lang.model.element.Element;

import junit.framework.Assert;
public class SportSettings {
	private Boolean countDown;
	private int maxTeamfouls;
	private int timeoutTime;
	private int timeoutBuzzer;
	private int shotClock;
	private int shotClockReset;

	/*
	 * NO OVERLOADED METHODS!!! for get/set/default <================================ VERY IMPORTANT!!!!
	 * 
	 * Getters must have zero input parameters (i.e. getFoo() )
	 * Setters must have exactly one input parameter (i.e. setFoo(Class bar) )
	 * Defaults must have zero input parameters (i.e. defaultFoo() )
	 */

	public Boolean getCountDown() {
		if (countDown == null) {
			this.defCountDown();
		}
		return countDown;
	}
	private void setCountDown(Boolean countDown) { 
		this.countDown = countDown;
	}
	private void defCountDown(){
		this.countDown = true;
	}
	public int getMaxTeamfouls() {
		return maxTeamfouls;
	}
	private void setMaxTeamfouls(int maxTeamfouls) {
		this.maxTeamfouls = maxTeamfouls;
	}
	private void defMaxTeamfouls() {
		this.maxTeamfouls = 5;
	}
	public int getTimeoutTime() {
		return timeoutTime;
	}
	private void setTimeoutTime(int timeoutTime) {
		this.timeoutTime = timeoutTime;
	}
	private void defTimeoutTime() {
		this.timeoutTime = 60;
	}
	public int getTimeoutBuzzer() {
		return timeoutBuzzer;
	}
	private void setTimeoutBuzzer(int timeoutBuzzer) {
		this.timeoutBuzzer = timeoutBuzzer;
	}
	private void defTimeoutBuzzer() {
		this.timeoutBuzzer = 50;
	}
	public int getShotClock() {
		return shotClock;
	}
	private void setShotClock(int shotClock) {
		this.shotClock = shotClock;
	}
	private void defShotClock() {
		this.shotClock = 24;
	}
	public int getShotClockReset() {
		return shotClockReset;
	}
	private void setShotClockReset(int shotClockReset) {
		this.shotClockReset = shotClockReset;
	}
	private void defShotClockReset() {
		this.shotClockReset = 14;
	}
	public void readSportSettings(String path){
		BufferedReader inputStream 	= null;
		String line;
		String word;
		String setMethodName;
		String defMethodName;
		String valueStr;
		Class<?>[] methodParType;
		Boolean goDefault;
		Method setMethod;
		Method defMethod;
		Object arglist[] 	= new Object[1];
		
		Method[] methodsArray = this.getClass().getDeclaredMethods();
		try{
			inputStream = new BufferedReader(new FileReader(path));
			while (inputStream.ready()) {
				goDefault 		= false;
				setMethodName 	= null;
				defMethodName	= null;
				valueStr		= null;
				line 			= null;
				word 			= null;
				setMethod 		= null;
				defMethod 		= null;
				arglist[0]		= null;

				line = inputStream.readLine();
				if(line.length()==0){
					continue; // empty line
				}
				Scanner s = new Scanner(line);
				try {
					word = s.next();
					if (word.contains("//")){
						throw new Exception("Line starts with slashes.");
					}	
				} catch (Exception e) {
					s.close();
					continue;
				}
				setMethodName = "set" + word;
				defMethodName = "default" + word;
				
				setMethod = findMethod(setMethodName, methodsArray);
				if(setMethod==null){
					s.close();
					continue; // no valid field/method name found on line, next line
				}
				defMethod = findMethod(defMethodName, methodsArray);

				try {
					s.next(); // read equals-sign
					methodParType 	= setMethod.getParameterTypes();
					if(methodParType.length>1){
						setAllDefault();
						break; // from while
					}
					if(isFirstParInt(methodParType)){
						arglist[0] = s.nextInt();
					} else if(isFirstParBool(methodParType)){
						valueStr = s.next();
						if(isStrTrueOrFalse(valueStr)){
							arglist[0] = new Boolean(Boolean.parseBoolean(valueStr));
						} else{
							throw new Exception();
						}
					} else{
						setAllDefault();
						break; // from while
					}
				} catch (Exception e) {
					goDefault = true;
					arglist[0] = null;
				}
				try {
					if(!goDefault){
						setMethod.setAccessible(true);
						setMethod.invoke(this, arglist);
						setMethod.setAccessible(false);
					} else{
						///
						defMethod.setAccessible(true);
						defMethod.invoke(this, null); // mind the 'null'
						defMethod.setAccessible(false);
					}
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}
				s.close();
			} // end while
		} catch (NoSuchElementException e){
			System.out.println("NoSuchElementException");
		} catch (IOException e) {
			e.printStackTrace();
		}
		finally{
			if (inputStream != null){
				try {
					inputStream.close();
				} catch (IOException e) {
				}
			}
		}
	} // end readSportSettings
	private boolean isFirstParInt(Class<?>[] methodParType) {
		return methodParType[0].getName().equals("int");
	}
	private boolean isFirstParBool(Class<?>[] methodParType) {
		return methodParType[0].getName().contains("Boolean");
	}
	private boolean isStrTrueOrFalse(String valueStr) {
		return valueStr.equalsIgnoreCase("true") || valueStr.equalsIgnoreCase("false");
	}

	private void setAllDefault() {
		this.defCountDown();
		this.defMaxTeamfouls();
		this.defShotClock();
		this.defShotClockReset();
		this.defTimeoutBuzzer();
		this.defTimeoutTime();
	}
	public static Method findMethod(String methodName, Method[] methodsArray) {
		for (Method method : methodsArray) {
			if(method.getName().equalsIgnoreCase(methodName)){
				return method;
			}
		}
		return null;
	}
	private static void testSettings() {
		String path = "C:/Users/Jochem/workspace/Scorebord/instellingen.txt";
		SportSettings sportSettings = new SportSettings();
		sportSettings.readSportSettings(path);
		System.out.println("Resultaten:");
		System.out.println("countdown: " + sportSettings.getCountDown());
		System.out.println("shotclock: " + sportSettings.getShotClock());
		System.out.println("shotclockreset: " + sportSettings.getShotClockReset());
		System.out.println("maxteamfouls: " + sportSettings.getMaxTeamfouls());
		System.out.println("timeoutbuzzer: " + sportSettings.getTimeoutBuzzer());
		System.out.println("timeouttime: " + sportSettings.getTimeoutTime());
	}
	public static void main(String[] args) {
		testSettings();
	}
}
